﻿// Copyright (c) 2010 Eugene Korneychuk (zhech)
// This source is subject to the  MIT License.
// http://zhechajaxcontrols.codeplex.com/license.
// All other rights reserved.
Type.registerNamespace("AjaxControlToolkit");

//States that reterned from server
AjaxControlToolkit.ExecutionResultState = function() {
    throw Error.invalidOperation();
}
AjaxControlToolkit.ExecutionResultState.prototype = {
    Undefined: 0,
    Executing: 1,
    Successed: 2,
    Error: 3,
    Canceled: 4,
    Started: 5,
    NotFound: 6
}
AjaxControlToolkit.ExecutionResultState.registerEnum('AjaxControlToolkit.ExecutionResultState');
//Commands that supported by server
AjaxControlToolkit.ExecutionCommands = function () {
    throw Error.invalidOperation();
}
AjaxControlToolkit.ExecutionCommands.prototype = {
    GetState: 0,
    CancelExecution: 1,
    StartExecution: 2
}
AjaxControlToolkit.ExecutionCommands.registerEnum('AjaxControlToolkit.ExecutionCommands');


AjaxControlToolkit.UpdatePanelExtender = function (element) {
    AjaxControlToolkit.UpdatePanelExtender.initializeBase(this, [element]);
    this._hiddenField = null;
    this._innerTB = null;
    this._postBackUrl = "";
    this._formName = "";
    this._iframe = null;
    this._waitTimer = null;
    this._updatePanel = null;
    this._animationextender = null;
    this._processGUID = null;
    this._wasCanceled = false;
    this._wasStarted = false;
    this._updatePanelRefreshFunction = null;
    this._onload$delegate = null;
    this._updatePeriod = 1000;
    this._popup = null;
    this._processingLabel = null;
    this._cancelButton = null;
    this._startUpOperation = null;
    this._isExecuting = true;
    this._isCanceling = false;
    this._wasCanceled = false;
    this._wasStarted = false;
}

AjaxControlToolkit.UpdatePanelExtender.prototype = {
    get_popup: function () {
        return this._popup;
    },
    set_popup: function (value) {
        this._popup = value;
    },
    get_processingLabel: function () {
        return this._processingLabel;
    },
    set_processingLabel: function (value) {
        this._processingLabel = value;
    },
    get_cancelButton: function () {
        return this._cancelButton;
    },
    set_cancelButton: function (value) {
        this._cancelButton = value;
    },
    get_updatePeriod: function () {
        return this._updatePeriod;
    },
    set_updatePeriod: function (value) {
        if (value > 0)
            this._updatePeriod = value;
    },
    get_updatePanelRefreshFunction: function () {
        return this._updatePanelRefreshFunction;
    },
    set_updatePanelRefreshFunction: function (value) {
        this._updatePanelRefreshFunction = value;
    },
    setPopup: function (value) {
        if (this._popup) {
            if (value) {
                this._popup.show();
            } else {
                this._popup.hide();
            }
        }
    },
    get_updatepanel: function () {
        return this._updatePanel;
    },
    set_updatepanel: function (value) {
        this._updatePanel = value;
    },
    get_animationextender: function () {
        return this._animationextender;
    },
    set_animationextender: function (value) {
        this._animationextender = value;
    },
    get_postBackUrl: function () {
        return this._postBackUrl;
    },
    set_postBackUrl: function (value) {
        this._postBackUrl = value;
    },
    get_formName: function () {
        return this._formName;
    },
    set_formName: function (value) {
        this._formName = value;
    },
    get_startUpOperation: function () {
        return this._startUpOperation;
    },
    set_startUpOperation: function (value) {
        this._startUpOperation = value;
    },
    //----------------------------------------------------------------------------
    initialize: function () {
        AjaxControlToolkit.UpdatePanelExtender.callBaseMethod(this, "initialize");
        this._iframeName = this.get_element().id + "_iframe";
        if (this.get_startUpOperation()) {
            var struct = Sys.Serialization.JavaScriptSerializer.deserialize('(' + this.get_startUpOperation() + ')');
            this._startUpOperation = null;
            this.WaitForExecutionComplete(struct.guid);
        }
        if (!this._processGUID) {
            this._freeUpdatePanel();
        }
    },
    dispose: function () {
        if (this._isExecuting) {
            this._sendCancelCommandNoWaitResult();
        } else {
            this._removeIframe();
        }
        AjaxControlToolkit.UpdatePanelExtender.callBaseMethod(this, "dispose");
    },
    //----------------------------------------------------------------------------
    _setProcessGUID: function (processGUID) {
        this._processGUID = processGUID
        var state = {
            processGUID: this._processGUID
        };
        var val = Sys.Serialization.JavaScriptSerializer.serialize(state);
        this.set_ClientState(val);
    },
    WaitForExecutionComplete: function (processGUID) {
        this._removeIframe();
        this._setProcessGUID(processGUID);
        this._wasCanceled = false;
        this._wasStarted = false;
        this._hookUpdatePanel();
        this._createIframe();
        this._isExecuting = true;
        this._processServerAnsver();
    },
    ClientStartExecution: function () {
        this._removeIframe();
        this._setProcessGUID(null);
        this._wasCanceled = false;
        this._wasStarted = true;
        this._hookUpdatePanel();
        this._createIframe();
        this._isExecuting = true;
        this._processServerAnsver();
    },
    CanelExecution: function () {
        this._wasCanceled = true;
        var response = {
            ExecutionResultState: AjaxControlToolkit.ExecutionResultState.Canceled
        };
        this._setProcessingStatus(response);
    },
    //----------------------------------------------------------------------------
    _createIframe: function () {
        try {
            if ((this._iframe == null) || !this._iframe) {
                this._onload$delegate = Function.createDelegate(this, this._processServerAnsver);
                var iframe = document.createElement("IFRAME");
                iframe.width = "0";
                iframe.height = "0";
                iframe.style.display = "none";
                iframe.src = "about:blank";
                iframe.id = this._iframeName;
                iframe.name = this._iframeName;
                $addHandlers(iframe, {
                    load: this._onload$delegate
                });
                this._iframe = iframe;
                document.body.appendChild(this._iframe);
                if (iframe.contentWindow) {
                    iframe.contentWindow.name = this._iframeName;
                }
            } else {
                this._removeIframe();
            }
        } catch (ex) {
            Err(ex, "\n");
        }
    },
    _removeIframe: function (clearProcessGUID) {
        this._removeTimer();
        if (this._iframe != null) {
            if (this._onload$delegate != null) {
                $common.removeHandlers(this._iframe, {
                    load: this._onload$delegate
                });
                this._onload$delegate = null;
            }
            document.body.removeChild(this._iframe);
            this._iframe = null;
        }
        if ((clearProcessGUID == true) || (clearProcessGUID == null) || (clearProcessGUID == 'undefined')) {
            this._setProcessGUID(null);
        }
        this._freeUpdatePanel();
    },
    _sendCancelCommandNoWaitResult: function () {
        if (this._isCanceling) {
            return;
        }
        this._isExecuting = false;
        if (this._iframe != null) {
            if (this._onload$delegate != null) {
                $common.removeHandlers(this._iframe, {
                    load: this._onload$delegate
                });
                this._onload$delegate = null;
            }
            this._sendCommandToServer(AjaxControlToolkit.ExecutionCommands.CancelExecution, this._updatePeriod);
            setTimeout(function () { }, 100);
            document.body.removeChild(this._iframe);
            this._iframe = null;
        }
        this._setProcessGUID(null);
        this._isCanceling = false;
    },
    _removeTimer: function () {
        if (this._waitTimer != null) {
            window.clearTimeout(this._waitTimer);
            this._waitTimer = null;
        }
    },
    _getCommandName: function (command) {
        if (command == AjaxControlToolkit.ExecutionCommands.GetState) {
            return "upegs";
        }
        else if (command == AjaxControlToolkit.ExecutionCommands.CancelExecution) {
            return "upece";
        }
        else if (command == AjaxControlToolkit.ExecutionCommands.StartExecution) {
            return "upse";
        }
        return "";
    },
    _getIframeDoc: function (iframe) {
        var doc = null;
        if (!doc && iframe.contentWindow) doc = iframe.contentWindow.document;
        if (!doc && iframe.contentDocument) doc = iframe.contentDocument;
        if (!doc && iframe.document) doc = iframe.document;
        return doc;
    },
    _sendCommandToServer: function (command, waitTimeout) {
        var commandName = this._getCommandName(command);
        if (!this._processGUID && (command != AjaxControlToolkit.ExecutionCommands.StartExecution)) {
            this._removeIframe();
            return;
        }
        var mainForm = document.getElementById(this._formName);
        var uploader = this;
        this._removeTimer();
        var url = this._postBackUrl;
        url += url.indexOf("?") === -1 ? "?" : "&";
        url += 'UpdatePanelExtenderCommand=' + commandName + "&elemid=" + this._id;
        if (this._processGUID) {
            url += '&UpdatePanelExtenderPorcessGUID=' + this._processGUID;
        }
        mainForm.action = url;
        mainForm.target = this._iframeName;
        cleanup = false;
        setTimeout(function () {
            mainForm.submit();
            uploader._waitTimer = setTimeout(function () { uploader._wait() }, waitTimeout);
        }, 0);
    },
    _processServerAnsver: function () {
        var cleanup = true;
        var cancelWithoutResponse;
        var mainForm = document.getElementById(this._formName);
        var answer = null;
        var uploader = this;
        try {
            var frameDocument = this._getIframeDoc(this._iframe);
            if (frameDocument == null || frameDocument.location == null) {
                var ex = { "message": "Unknown server error" };
                throw (ex);
            } else if (frameDocument.location.href == 'about:blank') {
                cleanup = false;
                if (this._wasCanceled) {
                    this._sendCommandToServer(AjaxControlToolkit.ExecutionCommands.CancelExecution, this._updatePeriod);
                } else if (this._wasStarted) {
                    this._sendCommandToServer(AjaxControlToolkit.ExecutionCommands.StartExecution, this._updatePeriod);
                } else {
                    this._sendCommandToServer(AjaxControlToolkit.ExecutionCommands.GetState, this._updatePeriod);
                }
                return true;
            } else {
                if (this._isCanceling) return true;
                if (frameDocument.body.innerHTML == "") {
                    setTimeout(function () { uploader._processServerAnsver() }, 100);
                    return true;
                }
                this._removeTimer();
                if (!this._wasCanceled) {
                    var result = frameDocument.getElementById(this._id);
                    var response = null;
                    var ex = null;
                    if (result != null) {
                        response = Sys.Serialization.JavaScriptSerializer.deserialize('(' + result.innerHTML + ')');
                    } else {
                        ex = { "message": "Server returned unknown answer" };
                    }
                    if (response) {
                        //отрабатываем ответ
                        this._setProcessingStatus(response);
                        if (response.ExecutionResultState == AjaxControlToolkit.ExecutionResultState.Successed) {
                            //successed - can refrash page content
                            mainForm.target = "_top";
                            mainForm.action = this._postBackUrl;
                            this._isExecuting = false;
                            if (this._updatePanel) {
                                this._removeIframe(false);
                                eval(this._updatePanelRefreshFunction);
                            }
                            this._setProcessGUID(null);
                            cleanup = true;
                        } else if (response.ExecutionResultState == AjaxControlToolkit.ExecutionResultState.Started) {
                            //process was started - wait for completion
                            this._setProcessGUID(response.ExecutionResult);
                            this._wasStarted = false;
                            setTimeout(function () { uploader._sendCommandToServer(AjaxControlToolkit.ExecutionCommands.GetState, 100) }, uploader._updatePeriod);
                            cleanup = false;
                        } else if (response.ExecutionResultState == AjaxControlToolkit.ExecutionResultState.Executing) {
                            //continue waiting
                            setTimeout(function () { uploader._sendCommandToServer(AjaxControlToolkit.ExecutionCommands.GetState, 100) }, uploader._updatePeriod);
                            cleanup = false;
                        } else if (response.ExecutionResultState == AjaxControlToolkit.ExecutionResultState.Undefined) {
                            //waiting (the task is push to queue but not started)
                            this._isExecuting = true;
                            setTimeout(function () { uploader._sendCommandToServer(AjaxControlToolkit.ExecutionCommands.GetState, 100) }, uploader._updatePeriod);
                            cleanup = false;
                        } else if (response.ExecutionResultState == AjaxControlToolkit.ExecutionResultState.NotFound) {
                            //something was happend with process - hide popup
                            cleanup = true;
                            ex = { "message": response.ExecutionResult };
                        } else if (response.ExecutionResultState == AjaxControlToolkit.ExecutionResultState.Canceled) {
                            //canceled - hide popup and remove iframe
                            mainForm.target = "_top";
                            mainForm.action = this._postBackUrl;
                            cleanup = true;
                            this._setProcessGUID(null);
                            this._isExecuting = false;
                        } else if (response.ExecutionResultState == AjaxControlToolkit.ExecutionResultState.Error) {
                            //exception - hide popup and remove iframe
                            mainForm.target = "_top";
                            mainForm.action = this._postBackUrl;
                            cleanup = true;
                            this._isExecuting = true;
                            ex = { "message": response.ExecutionResult };
                        }
                    }
                    else {
                        this._wasCanceled = false;
                        cleanup = false;
                        this._sendCommandToServer(AjaxControlToolkit.ExecutionCommands.CancelExecution, this._updatePeriod);
                    }
                    if (ex) {
                        throw (ex);
                    }
                } else {
                    cleanup = true;
                    this._freeUpdatePanel();
                }
            }
        }
        catch (ex) {
            Err(ex, "\n");
            if (!this._isCanceling) {
                if (this._isExecuting) {
                    this._sendCancelCommandNoWaitResult();
                }
                this._removeTimer();
                mainForm.target = "_top";
                mainForm.action = this._postBackUrl;
                this._freeUpdatePanel();
            }
        }
        finally {
            if (cleanup) {
                setTimeout(function () { uploader._removeIframe(); }, 100);
            }
        }
    },
    _wait: function () {
        if (this._waitTimer == null) {
            return;
        }
        var uploader = this;
        try {
            var frameDocument = this._getIframeDoc(this._iframe);
            var location = frameDocument.location;
            var href = location.href;
            if (!this._isCanceling)
                this._waitTimer = setTimeout(function () { uploader._wait() }, 100);
        } catch (ex) {
            Err(ex, "\n");
            setTimeout(function () { uploader._removeIframe(); }, 100);
            this._waitTimer = null;
        }
    },
    _setProcessingStatus: function (response) {
        if (this._processingLabel) {
            if (response) {
                switch (response.ExecutionResultState) {
                    case AjaxControlToolkit.ExecutionResultState.Undefined:
                        $(this._processingLabel).text(AjaxControlToolkit.Resources.UpdatePanelEx_started);
                        break;
                    case AjaxControlToolkit.ExecutionResultState.Executing:
                        $(this._processingLabel).text(String.format(AjaxControlToolkit.Resources.UpdatePanelEx_processing, response.TotalSeconds));
                        break;
                    case AjaxControlToolkit.ExecutionResultState.Error:
                        $(this._processingLabel).text(String.format(AjaxControlToolkit.Resources.UpdatePanelEx_error, response.ExecutionResult));
                        setTimeout(function () { }, this._updatePeriod);
                        break;
                    case AjaxControlToolkit.ExecutionResultState.Successed:
                        $(this._processingLabel).text(AjaxControlToolkit.Resources.UpdatePanelEx_successed);
                        break;
                    case AjaxControlToolkit.ExecutionResultState.Canceled:
                        $(this._processingLabel).text(AjaxControlToolkit.Resources.UpdatePanelEx_canceled);
                        break;
                    case AjaxControlToolkit.ExecutionResultState.Canceled:
                        $(this._processingLabel).text(AjaxControlToolkit.Resources.UpdatePanelEx_started);
                        break;
                }
            } else {
                $(this._processingLabel).text(AjaxControlToolkit.Resources.UpdatePanelEx_started);
            }
        }
    },
    _hookUpdatePanel: function () {
        //функция, которая находит панель, устанавливает у нее тригер на аплоад
        if (this._animationextender) {
            this._animationextender._onUpdated.quit();
            this._animationextender._onUpdating.play();
        }
        this.setPopup(true);
    },
    _freeUpdatePanel: function () {
        //функция, которая находит панель и убирает у нее тригер на аплоад
        if (this._animationextender) {
            this._animationextender._onUpdating.quit();
            this._animationextender._onUpdated.play();
        }
        this.setPopup(false);
    }
}

AjaxControlToolkit.UpdatePanelExtender.registerClass("AjaxControlToolkit.UpdatePanelExtender", AjaxControlToolkit.BehaviorBase);